﻿#include "framework.h"
#include "LogonWindow.h"
#include "Protocol.h"
#include "Resource.h"

#ifndef STRING_BUF_LEN
#define STRING_BUF_LEN 256
#endif

// 函数声明
static void LogonWindow_Delete(LogonWindow*);
static INT_PTR LogonWindow_DoModal(LogonWindow*);
static void LogonWindow_OnOK(LogonWindow*);
static INT_PTR CALLBACK LogonWindow_Proc(HWND, UINT, WPARAM, LPARAM);

/**
 * 创建登录窗口。
 * @param parent    父窗口
 * @return 登录窗口
 */
LogonWindow* New_LogonWindow(HWND parent) {
    LogonWindow* logonWindow = (LogonWindow*)calloc(1, sizeof(LogonWindow));

    // 初始化数据
    logonWindow->mParent = parent;
    logonWindow->mUsername = (LPTSTR)calloc(1, USERNAME_BUF_LEN * sizeof(TCHAR));
    logonWindow->mPassword = (LPTSTR)calloc(1, PASSWORD_BUF_LEN * sizeof(TCHAR));

    // 初始化函数
    logonWindow->deleteSelf = LogonWindow_Delete;
    logonWindow->doModal = LogonWindow_DoModal;

    return logonWindow;
}

/**
 * 删除登录窗口。
 * @param logonWindow   登录窗口
 */
static void LogonWindow_Delete(LogonWindow* logonWindow) {
    free(logonWindow->mUsername);
    free(logonWindow->mPassword);
    free(logonWindow);
}

/**
 * 以模态显示窗口。
 * @param logonWindow   登录窗口
 * @return 为 IDOK 表示用户单击了"确定"按钮，为 IDCANCEL 表示用户单击了"取消"按钮
 */
static INT_PTR LogonWindow_DoModal(LogonWindow* logonWindow) {
    return DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_LOGON_WINDOW), 
        logonWindow->mParent, LogonWindow_Proc, (LPARAM)logonWindow);
}

/**
 * "确定"按钮的单击响应函数。
 * @param logonWindow   登录窗口
 */
static void LogonWindow_OnOK(LogonWindow* logonWindow) {
    LPTSTR username = (LPTSTR)calloc(1, USERNAME_BUF_LEN * sizeof(TCHAR));  // 用户输入的用户名
    LPTSTR password = (LPTSTR)calloc(1, PASSWORD_BUF_LEN * sizeof(TCHAR));  // 用户输入的密码
    TCHAR text[STRING_BUF_LEN] = { 0 };                                     // 提示信息

    // 检查用户名是否为空
    GetDlgItemText(logonWindow->mHandle, IDC_EDIT_USERNAME, username, USERNAME_BUF_LEN);
    if (_tcscmp(username, _T("")) == 0) {
        LoadString(NULL, IDS_USERNAME_EMPTY, text, STRING_BUF_LEN);
        MessageBox(logonWindow->mHandle, text, _T(" "), MB_ICONERROR);
        SetFocus(GetDlgItem(logonWindow->mHandle, IDC_EDIT_USERNAME));
        free(username);
        free(password);
        return;
    }

    // 检查密码是否为空
    GetDlgItemText(logonWindow->mHandle, IDC_EDIT_PASSWORD, password, PASSWORD_BUF_LEN);
    if (_tcscmp(password, _T("")) == 0) {
        LoadString(NULL, IDS_PASSWORD_EMPTY, text, STRING_BUF_LEN);
        MessageBox(logonWindow->mHandle, text, _T(" "), MB_ICONERROR);
        SetFocus(GetDlgItem(logonWindow->mHandle, IDC_EDIT_PASSWORD));
        free(username);
        free(password);
        return;
    }

    // 保存用户名、密码
    _tcscpy_s(logonWindow->mUsername, USERNAME_BUF_LEN, username);
    _tcscpy_s(logonWindow->mPassword, PASSWORD_BUF_LEN, password);
    free(username);
    free(password);

    // 关闭窗口
    EndDialog(logonWindow->mHandle, IDOK);
}

/**
 * 窗口过程函数。
 * @param window    窗口
 * @param message   事件标识
 * @param wParam    事件相关信息
 * @param lParam    事件相关信息
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
static INT_PTR CALLBACK LogonWindow_Proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    LogonWindow* logonWindow = (LogonWindow*)GetWindowLongPtr(window, GWLP_USERDATA);
    WORD id = LOWORD(wParam);

    switch (message) {
        case WM_COMMAND:
            if (id == IDOK) {
                LogonWindow_OnOK(logonWindow);
                return TRUE;
            }
            if (id == IDCANCEL) {
                EndDialog(window, id);
                return TRUE;
            }
            break;
        case WM_INITDIALOG:
            logonWindow = (LogonWindow*)lParam;
            logonWindow->mHandle = window;
            SetWindowLongPtr(logonWindow->mHandle, GWLP_USERDATA, (LONG_PTR)logonWindow);

            // 设置最大用户名长度和最大密码长度
            SendMessage(GetDlgItem(logonWindow->mHandle, IDC_EDIT_USERNAME), EM_SETLIMITTEXT, MAX_USERNAME_LEN, 0);
            SendMessage(GetDlgItem(logonWindow->mHandle, IDC_EDIT_PASSWORD), EM_SETLIMITTEXT, MAX_PASSWORD_LEN, 0);
            return TRUE;
        }
        return FALSE;
}
